package com.thinkit.bigdata.web.controller.system;

import com.thinkit.bigdata.core.util.*;
import com.thinkit.bigdata.core.util.es.ESUtil;
import com.thinkit.bigdata.core.util.excel.XlsUtil;
import com.thinkit.bigdata.web.coremet.SystemStatic;
import com.thinkit.bigdata.web.model.result.Constants;
import com.thinkit.bigdata.web.model.result.HtmlResult;
import com.thinkit.bigdata.web.model.sec.User;
import com.thinkit.bigdata.web.model.sec.UserExample;
import com.thinkit.bigdata.web.model.sys.*;
import com.thinkit.bigdata.web.service.sec.UserService;
import com.thinkit.bigdata.web.service.sys.SysApprovalConfigService;
import com.thinkit.bigdata.web.service.sys.SysApprovalDataService;
import com.thinkit.bigdata.web.service.sys.SysApprovalTaskService;
import com.thinkit.bigdata.web.service.sys.SysExportUserParamService;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 审批流程：
 *      1，前置条件：
 *          1)，在审批数据表中配置好没个需要审批的数据，例如：导出用户详情
 *          2)，在审批流程配置表中配置好每个审批数据的审批流程
 *      2，审批数据操作：
 *          1)，操作审批数据，便会在审批任务表中增加一条审批任务数据，同时会将改消息推送到审批人的任务列表中，若是已存在改任务，判断是否
 *          审批通过，可以直接导出了，给除相应的反应或者提示信息。
 *          2)，在操作审批数据的时候，需要将需要导出的数据的范围条件保存，例如用户详情导出，需要保存到用户详情导出体条件表中
 *      3，审批操作：
 *          1)，审批人在审批处审批数据，一个接一个，直到最高审批人同意之后，直接生成文件，导出人可以直接在审批通过处下载
 *          2)，审批人中又任何一个人审核不通过，即审批流程结束，为不通过，不管后续有没有需要审批的人员
 *          3)，审批人在审批一次，便记录一次，审批记录表中
 *      4，审批数据导出：
 *          1)，导出人在审批通过处，即审批任务记录中可以直接导出该文件
 *          2)，导出时，会在导出记录表中记录该动作
 *      5，至此【导出-审批】流程结束
 */
@RestController
@RequestMapping("/approval")
public class SysApprovalController {

    private static Logger logger = Logger.getLogger(SysApprovalController.class);

    private static String DATA_LOG_MES = "【审批数据操作】";

    private static String CONFIG_LOG_MES = "【审批流程配置操作】";

    private static String EXPORT_LOG_MES = "【导出操作】";

    @Resource
    private UserService userService;

    @Resource
    private SysApprovalDataService dataService;

    @Resource
    private SysApprovalConfigService configService;

    @Resource
    private SysApprovalTaskService taskService;

    @Resource
    private SysExportUserParamService userParamService;

    @Resource
    private ESUtil esUtil;

    @Resource
    private ProjectPubMet pubMet;

//######################################################################################################################
//                                   审批数据
//######################################################################################################################

    @RequestMapping(value = "/data-page", method = RequestMethod.POST)
    public HtmlResult dataPage(@RequestBody SysApprovalDataDto dto) {
        logger.info(DATA_LOG_MES + "分页查询");
        logger.info(DATA_LOG_MES + dto.toString());
        return dataService.selectByExample(dto);
    }

    @RequestMapping(value = "/data-list", method = RequestMethod.POST)
    public HtmlResult dataList() {
        logger.info(DATA_LOG_MES + "查询");
        return dataService.selectByExample();
    }

    @RequestMapping(value = "/data-add", method = RequestMethod.POST)
    public HtmlResult dataAdd(@RequestBody SysApprovalData data) {
        logger.info(DATA_LOG_MES + "添加");
        logger.info(DATA_LOG_MES + data.toString());
        return dataService.insertSelective(data);
    }

    @RequestMapping(value = "/data-update", method = RequestMethod.POST)
    public HtmlResult dataUpdate(@RequestBody SysApprovalData data) {
        logger.info(DATA_LOG_MES + "修改");
        logger.info(DATA_LOG_MES + data.toString());
        return dataService.updateByPrimaryKey(data);
    }

    @RequestMapping(value = "/data-del", method = RequestMethod.POST)
    public HtmlResult dataDel(@RequestParam(value = "codes") final String codes) {
        logger.info(DATA_LOG_MES + "删除");
        logger.info(DATA_LOG_MES + "codes = "  + codes);
        return dataService.deleteByPrimaryKey(codes);
    }

    @RequestMapping(value = "/uniqueness-code", method = RequestMethod.POST)
    public HtmlResult uniquenessCode(@RequestParam(value = "code") final String code) {
        logger.info(DATA_LOG_MES + "数据标识唯一性判断");
        logger.info(DATA_LOG_MES + "code = "  + code);
        return dataService.uniquenessCode(code);
    }

    @RequestMapping(value = "/uniqueness-name", method = RequestMethod.POST)
    public HtmlResult uniquenessName(
            @RequestParam(value = "code") final String code,
            @RequestParam(value = "name") final String name) {
        logger.info(DATA_LOG_MES + "数据名称唯一性判断");
        logger.info(DATA_LOG_MES + "code = " + code + ", name = " + name);
        return dataService.uniquenessName(code, name);
    }

//######################################################################################################################
//                                   审批流程配置
//######################################################################################################################

    @RequestMapping(value = "/config-page", method = RequestMethod.POST)
    public HtmlResult configPage(@RequestBody SysApprovalConfigSeach seach) {
        logger.info(CONFIG_LOG_MES + "分页查询");
        logger.info(CONFIG_LOG_MES + seach.toString());
        return configService.selectByExample(seach);
    }

    @RequestMapping(value = "/config-add", method = RequestMethod.POST)
    public HtmlResult configAdd(@RequestBody SysApprovalConfigDto dto) {
        logger.info(CONFIG_LOG_MES + "添加");
        logger.info(CONFIG_LOG_MES + dto.toString());
        try {
            return configService.insertSelective(dto);
        } catch (Exception e) {
            e.printStackTrace();
            return HtmlResult.failure("添加失败");
        }
    }

    @RequestMapping(value = "/config-update", method = RequestMethod.POST)
    public HtmlResult configUpdate(@RequestBody SysApprovalConfigDto dto) {
        logger.info(CONFIG_LOG_MES + "修改");
        logger.info(CONFIG_LOG_MES + dto.toString());
        try {
            return configService.updateByPrimaryKey(dto);
        } catch (Exception e) {
            e.printStackTrace();
            return HtmlResult.failure("修改失败");
        }
    }

    @RequestMapping(value = "/config-del", method = RequestMethod.POST)
    public HtmlResult configDel(@RequestParam(value = "ids") final String ids) {
        logger.info(CONFIG_LOG_MES + "删除");
        logger.info(CONFIG_LOG_MES + "ids = " + ids);
        return configService.deleteByPrimaryKey(ids);
    }

//######################################################################################################################
//                                   审批任务
//######################################################################################################################

    @RequestMapping(value = "/export-task-search", method = RequestMethod.POST)
    public HtmlResult exportTaskSearch(@RequestBody SysApprovalTaskSearch task) {
        logger.info(EXPORT_LOG_MES + "分页查询导出审批任务");
        logger.info(EXPORT_LOG_MES + "task = " + task.toString());
        try {
            return taskService.exportTaskSearch(task);
        } catch (Exception e) {
            e.printStackTrace();
            return HtmlResult.failure(EXPORT_LOG_MES + "查询失败");
        }
    }

    @RequestMapping(value = "/export-task-param-search", method = RequestMethod.POST)
    public HtmlResult exportTaskParamSearch(@RequestParam(value = "id") final Long id) {
        logger.info(EXPORT_LOG_MES + "审批任务条件");
        logger.info(EXPORT_LOG_MES + "id = " + id);
        return taskService.exportTaskParamSearch(id);
    }

    @RequestMapping(value = "/add-export-task", method = RequestMethod.POST)
    public void addExportTask(HttpServletRequest request, HttpServletResponse response) {
        logger.info(EXPORT_LOG_MES + "导出操作任务创建");
        String code = request.getParameter("code");
        String note = request.getParameter("note");
        String areaId = request.getParameter("areaId");
        String groupId = request.getParameter("groupId");
        String account = request.getParameter("account");
        String userName = request.getParameter("userName");
        String realName = request.getParameter("realName");
        String status = request.getParameter("status");
        String fileContent = request.getParameter("fileContent");
        String fileContext = request.getParameter("fileContext");
        logger.info(EXPORT_LOG_MES + "code = " + code);
        logger.info(EXPORT_LOG_MES + "note = " + note);
        logger.info(EXPORT_LOG_MES + "areaId = " + areaId);
        logger.info(EXPORT_LOG_MES + "groupId = " + groupId);
        logger.info(EXPORT_LOG_MES + "account = " + account);
        logger.info(EXPORT_LOG_MES + "userName = " + userName);
        logger.info(EXPORT_LOG_MES + "realName = " + realName);
        logger.info(EXPORT_LOG_MES + "status = " + status);
        logger.info(EXPORT_LOG_MES + "fileContent = " + fileContent);
        logger.info(EXPORT_LOG_MES + "fileContext = " + fileContext);
        try {
            List<String> files = Arrays.asList(fileContent.split(","));
            if (!files.contains("mobileno") && !files.contains("idcard")) {
                logger.info(EXPORT_LOG_MES + "没有敏感信息");
                //获取用户导出用户信息
                List<Map<String, Object>> userList = getExportUserList(request);
                XlsUtil.exportUser(
                        userList,
                        fileContent,
                        SystemStatic.SYSTEM_USER_PATH_EXPORT + "用户明细_" + DateFormatUtil.getDataTime()+ ".xls",
                        response,
                        "noMi"
                );
            } else {
                HtmlResult result = taskService.addExportTask(request);
                response.setCharacterEncoding("UTF-8");
                response.setContentType("text/html;charset=utf-8");
                PrintWriter out = response.getWriter();
                out.print(result);
                out.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 共用的导出下载用户信息
    private List<Map<String, Object>> getExportUserList(HttpServletRequest request) {
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        // 获取查询条件：选中了哪几条数据
        String userIdList = request.getParameter("userIdList");
        // 如果选中的userId不为空 则只导出对应的用户信息
        if(StringUtil.isNotEmpty(userIdList)){
            String[] array = userIdList.split(",");
            List<Long> idList = new ArrayList<>();
            for (String userId : array) {
                try {
                    idList.add(Long.valueOf(userId));
                } catch (NumberFormatException e) {
                    // 格式化错误的不用管
                    e.printStackTrace();
                }
            }
            if(!userIdList.isEmpty()){
                criteria.andIdIn(idList);
            }
        } else {
            // 其他查询条件
            String areaId = request.getParameter("areaId");   //省份id
            String groupId = request.getParameter("groupId");   //组织机构id
            String account = request.getParameter("account");   //工号
            String userName = request.getParameter("userName"); //用户名
            String realName = request.getParameter("realName"); //真实姓名
            String status = request.getParameter("status"); //状态
            // 限制超管和省份人员不能查询出自己进行操作 只有集团人员能查询出来自己
            User user = (User) SecurityUtils.getSubject().getSession().getAttribute(Constants.SESSION_USER_INFO);
            if (user.getGroupid() == null || user.getGroup().getAreaid().longValue() != Constants.GROUP_AREAID.longValue()) {
                // 如果用户所属机构为null(说明为admin) 用户所属省份id不为集团id 则限制用户不能查询出来自己
                criteria.andIdNotEqualTo(user.getId());
            }
            // 限制用户不能查询出来admin 如果groupid不为空 肯定查询不出来admin 如果为空 则设置groupid不能为空（admin没有groupid）
            if (StringUtil.isEmpty(groupId)) {
                criteria.andGroupidIsNotNull();
                // 当groupId为空 判断areaid 获取当前登录用户允许访问的组织机构范围
                List<Long> subGroupIdList = userService.getAllSubGroupId(areaId);
                if (!subGroupIdList.isEmpty()) {
                    criteria.andGroupidIn(subGroupIdList);
                }
            }
            if (StringUtil.isNotEmpty(groupId) && groupId.matches("\\d*")) {
                criteria.andGroupidEqualTo(Long.valueOf(groupId));
            }
            if (StringUtil.isNotEmpty(account)) {
                criteria.andAccountLike("%" + account + "%");
            }
            if (StringUtil.isNotEmpty(userName)) {
                criteria.andUsernameLike("%" + userName + "%");
            }
            if (StringUtil.isNotEmpty(realName)) {
                criteria.andRealnameLike("%" + realName + "%");
            }
            if (StringUtil.isNotEmpty(status)) {
                String[] isDeleteArray = status.split(",");
                List<Integer> isDeleteList = new ArrayList<>();
                for (String s : isDeleteArray) {
                    try {
                        isDeleteList.add(Integer.valueOf(s));
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                }
                criteria.andIsdeleteIn(isDeleteList);
            }
        }
        String sortName = request.getParameter("sortName"); //排序名称
        String sortOrder = request.getParameter("sortOrder"); //排序方式
        example.setOrderByClause(sortName + " " + sortOrder);
        return userService.selectUserDataToExport(example);
    }

    @RequestMapping(value = "/update-export-task", method = RequestMethod.POST)
    public HtmlResult updateExportTask(
            @RequestParam(value = "id") final Long id,
            @RequestParam(value = "status") final int status,
            @RequestParam(value = "note") final String note,
            HttpServletResponse response
    ) {
        logger.info(EXPORT_LOG_MES + "批复审批任务");
        logger.info(EXPORT_LOG_MES + "id = " + id);
        logger.info(EXPORT_LOG_MES + "status = " + status + ":" + esUtil.changeExportTaskStatus(status));
        logger.info(EXPORT_LOG_MES + "note = " + note);
        try {
            return taskService.updateExportTask(id, status, note, response);
        } catch (IOException e) {
            e.printStackTrace();
            return HtmlResult.failure("批复审批任务出错");
        }
    }

    @RequestMapping(value = "/del-export-task", method = RequestMethod.POST)
    public HtmlResult delExportTask(@RequestParam(value = "ids") final String ids) {
        logger.info(EXPORT_LOG_MES + "删除审批任务");
        logger.info(EXPORT_LOG_MES + "ids = " + ids);
        return taskService.delExportTask(ids);
    }

    @RequestMapping(value = "/export-file-task", method = RequestMethod.POST)
    public void exportFileTask(@RequestParam(value = "id") final Long id, HttpServletResponse response) {
        logger.info(EXPORT_LOG_MES + "下载导出的文件操作");
        logger.info(EXPORT_LOG_MES + "id = " + id);
        try {
            HtmlResult result = taskService.exportFileTask(id, response);
            String resultStr = result.getMsg();
            if (result.getCode() == 0) {
                SysExportUserParam param = userParamService.selectByPrimaryKey(id);
                //登陆ftp
                FtpUtil ftpUtil = pubMet.getFtpUtil();
                if (!ftpUtil.isExsits(param.getFileurl())) {
                    throw new RuntimeException();
                }
                String localPath = SystemStatic.SYSTEM_USER_PATH_EXPORT + param.getFilename();
                //从ftp获取到本地
                if (!ftpUtil.downloadFile(param.getFileurl(), localPath)) {
                    throw new RuntimeException();
                }
                //关闭ftp链接
                ftpUtil.disconnect();
                File file = new File(localPath);
                FileUtil.downloadFile(file, response);
                FileUtil.deleteFile(file);
            }
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=utf-8");
            PrintWriter out = response.getWriter();
            out.print(resultStr);
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
